
package hk.ces.oxfam.patch.db.sql;

import hk.ces.oxfam.patch.util.StringUtil;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author ReutyCheng
 */
public class PreparedSQL
{
  public static final String BASE_SQLS = "BASE_SQLS";
  private String sql;
  private Object[] params;
  private Map<String, String> meta = new HashMap<String, String>();

  public PreparedSQL(String sql, Object[] params)
  {
    this.sql = sql;
    this.params = params;
  }

  public Object[] getParams()
  {
    return params;
  }

  public String getSql()
  {
    return sql;
  }

  public void addMeta(String metaKey, String metaValue)
  {
    this.meta.put(metaKey, metaValue);
  }

  public Map<String, String> getMetas()
  {
    return meta;
  }

  public void setBaseSQLs(PreparedSQL... baseSQLs)
  {
    if (!sql.contains(BASE_SQLS) || StringUtil.count(sql, BASE_SQLS) != baseSQLs.length)
    {
      throw new IllegalArgumentException("SQLResult(s) Count[" + baseSQLs.length + "] not match [" + BASE_SQLS + "] mark to in SQL[" + sql + "]");
    }

    for (PreparedSQL preparedSQL : baseSQLs)
    {
      this.redefinedSqlAndParamsByBaseResult(preparedSQL);
    }
  }

  private void redefinedSqlAndParamsByBaseResult(PreparedSQL preparedSQL)
  {
    String redefinedSql = sql.replaceFirst(BASE_SQLS, preparedSQL.getSql());

    int redefinedParamsCount = params.length + preparedSQL.getParams().length;
    Object[] redefinedParams = new Object[redefinedParamsCount];

    char questionMark = '?';
    String[] sqlFragment = sql.split(BASE_SQLS);
    int countQuestionMarkInFrontSql = StringUtil.count(sqlFragment[0], questionMark);
    int countQuestionMarkInEndSql = StringUtil.count(sqlFragment[1], questionMark);

    int redefinedParamIndex = 0;

    for (int index = 0; index < countQuestionMarkInFrontSql; index++)
    {
      redefinedParams[redefinedParamIndex++] = params[index];
    }
    for (int index = 0; index < preparedSQL.getParams().length; index++)
    {
      redefinedParams[redefinedParamIndex++] = preparedSQL.getParams()[index];
    }
    for (int index = 0; index < countQuestionMarkInEndSql; index++)
    {
      redefinedParams[redefinedParamIndex++] = params[countQuestionMarkInFrontSql + index];
    }

    this.sql = redefinedSql;
    this.params = redefinedParams;
  }

  @Override
  public String toString()
  {
    return sql;
  }
}
